#ifndef INCLUDE_FS_H_
#define INCLUDE_FS_H_

#include "type.h"

// ---------------
// | super block |
// ---------------
// |  inode map  |
// ---------------
// | sector map  |
// ---------------
// |    inode    |
// ---------------
// |    data     |
// ---------------

#define KFS_MAGIC (0x66666666)
#define OFFSET_256M (0X10000000)
#define OFFSET_512M (0x20000000)
#define OFFSET_1G (0x40000000)
#define OFFSET_2G (0x80000000)
#define OFFSET_3G (0xC0000000)

#define SUPERBLK_OFFSET 0X200
#define BMAP_OFFSET 0x4000
#define IMAP_OFFSET 0X200
#define INODE_OFFSET 0x40000

#define OFFSET_FS OFFSET_512M

#define SUPERBLK_ADDR   0xffffffffa0100000//512B
#define BLKMAP_ADDR     0xffffffffa0100200//16KB
#define INODEMAP_ADDR   0xffffffffa0104200//512B
#define INODE_ADDR      0xffffffffa0104400//256KB
#define DATABLK_ADDR    0xffffffffa0144400

#define SD_SUPERBLK_ADDR   0x20000000//512B
#define SD_BLKMAP_ADDR     0x20000200//16KB
#define SD_INODEMAP_ADDR   0x20004200//512B
#define SD_INODE_ADDR      0x20004400//256KB
#define SD_DATABLK_ADDR    0x20044400



#define FS_SIZE (0x20000000)
//#define FS_SIZE (0x10000000)

#define NUM_IMAP_SECTOR 1
#define SECTOR_SIZE 512
#define NUM_FD 15
#define BLOCK_SIZE 0x1000
#define DENTRY_SIZE 32
#define INODE_SIZE 64

#define ENTRY_SECTOR 8

#define TYPE_FILE 1
#define TYPE_DIR 2

#define O_RDONLY 1
#define O_WRONLY 2
#define O_RDWR 3

// offset is sector offset
typedef struct super_block
{
    uint32_t magic_num; 
    uint32_t fs_sz; 

    uint64_t blockmap_addr;

    uint64_t inodemap_addr;

    uint64_t inodes_addr;
    uint32_t inodes_num;

    uint64_t datablock_addr;
    uint32_t datablock_num;
} super_block_t;
//ientry size : 64B
typedef struct inode_entry 
{
    uint32_t num;              // inode order
    uint16_t file_mode;        // 1 for r; 2 for w; 3 for r/w  
    uint16_t ref;              //hard_link num
    uint32_t i_mode;           //0 for file ; 1 for dir_entry ; 2 for soft link file
    uint32_t filesz;           //filesz
    uint32_t son_num;          //num of son dentry and file for dir or num of blocks for files
    uint32_t direct[9];        //direct addr to data block
    uint32_t indirect[2];      //level 1 indirect addr to data block
} inode_entry_t;

//dentry size : 32B
typedef struct dir_entry  
{
    uint32_t inode_id;
    uint32_t type;           // 1: file; 2: directory; 3:"."; 4:"..";5:soft link file
    char name[24];
} dir_entry_t;

typedef struct fd
{
    uint32_t cur_wpos;
    uint32_t inum;
    uint32_t availability; // 1 for r; 2 for w; 3 for r/w
    uint32_t cur_rpos;
} fd_t;

//extern inode_entry_t current_dir_entry;

void init_fs();
 
void read_super_block();

 
int readdir(char *name);
int mkdir(char *name);
int rmdir(char *name);
int mknod(char *name);

int open(char *name, uint32_t access);
int write(uint32_t fd, char *buff, uint32_t size);
int read(uint32_t fd, char *buff, uint32_t size);
int close(uint32_t fd);
int cat(char *name);

void do_mkfs();
void statfs();
int cd(char *dir);
int hard_link(char *oldfile, char *newfile);
int soft_link(char *oldfile, char *newfile);
#endif